#define DIV_CEIL(a, b)         (((a) > 0) ? (((a)-1)/(b) + 1) : 0)
#define DIV_ROUND(a, b)        ((a)/(b) + (((a)%(b)) > (b)/2))
#define BV_SET(bv, index, bit) ((bv)[(index) >> 3] = (bit) ? (bv)[(index) >> 3] | (1u << ((index) & 7)) : (bv)[(index) >> 3] & ~(1u << ((index) & 7)))
#define BV_GET(bv, index)      (((bv)[(index) >> 3] >> ((index) & 7)) & 1)
#define MAX(a, b)              (((a) > (b)) ? (a) : (b))
#define MIN(a, b)              (((a) < (b)) ? (a) : (b))
#define SQR(a)                 ((a)*(a))
#define VALUE_SHUFFLE(id)      (((id) + 7219)*16127)
#define SIGN(a)                ((a) >= 0)
#define INT_TO_UINT(a)         ((abs(a) << 1) | SIGN(a))
#define UINT_TO_INT(a)         ((((a) & 0x01) ? 1 : -1)*((a) >> 1))

#define INT_MAX    32767

#define NODEBUSY_FILE      "state/nodebusy%d.txt"
#define ERRORLOG_FILE      "error_log.txt"

                               // LED status:  slow blink - changes state once every two cycles. fast blink changes state every cycle
#define GS_IDLE            0   // red: off,         green: off                Node is idle (waiting for queries to begin, finished with queries...
#define GS_ERROR           1   // red: slow blink,  green: off                Various errors. Set by pause_sim().
#define GS_DISCOVERY       2   // red: fast blink,  green: off                Discovery message has been sent. Currently no realiable neighbors
#define GS_TREEBUILD       3   // red: on,          green: off                Tree building message has been sent.
#define GS_TREECOMMITWAIT  4   // red: off,         green: slow blink         Waiting for tree commit. Need to clear uart messages or sample static attrs.
#define GS_TREECOMMIT      5   // red: slow blink,  green: slow blink         Committing trees.
#define GS_ROUTE           6   // red: fast blink,  green: slow blink         Query initiation routing.
#define GS_TUPLEEVAL       7   // red: on,          green: slow blink         Evaluating tuples.
#define GS_TUPLESENT       8   // red: off,         green: fast blink         Sending tuples.
#define GS_DISCOVERY_N     9   // red: slow blink,  green: fast blink         Discovery message sent. At least one reliable neighbor. No path to root.
#define GS_DISCOVERY_R    10   // red: fast blink,  green: fast blink         Discovery message sent. At least one reliable neighbor and a path to root.
#define GS_RESETREQUESTED 11   // red: on,          green: fast blink         Reset has been requested. Waiting for outgoing messages to clear before resetting.

#define CONG_MINHEAP      500  // free memory below this triggers congestion bit
#define CONG_MINOUTPUT      2  // free outputbuffer slots below this trigger congestion bit
#define CONG_MINFRAGMENT    2  // free fragmentbuffer slots below this trigger congestion bit
#define CONG_MINMERGE       2  // free mergebuffer slots...
#define CONG_MINPAYLOAD     1  // free payloadbuffer slots...

#ifdef USE_BLUSH
#ifdef SAVE_DEBUG
#define MAX_DEBUGSTR       1000
char *save_debug[MAX_DEBUGSTR];
int savedebug_begin, savedebug_end;
#endif
#endif

#ifdef TOSSIM
  #define DBGOUT debug_str[0] = 0, dbgout
  #define DBGERR snprintf(debug_str, sizeof(debug_str), "%s: ", __FUNCTION__), format_debugstr(), dbgout
#else
#ifdef USE_BLUSH
  #define DBGOUT debug_str[0] = 0, dbgout
  #define DBGERR snprintf(debug_str, sizeof(debug_str), "%s: ", __FUNCTION__), format_debugstr(), dbgout
#else
  #define DBGOUT dbgout
  #define DBGERR dbgout
#endif
#endif  

//#define PERFORM_STACKTEST    // if defined, will perform stack depth measurements

#ifdef PERFORM_STACKTEST
uint8_t *basestack_ptr;
int max_stackusage;
#define INIT_STACKTEST       uint8_t __stacktest; basestack_ptr = &__stacktest; DBGOUT("Start stack test at %s, %d", __FUNCTION__, __LINE__);
#define END_STACKTEST        basestack_ptr = NULL; DBGOUT("End stack test at %s, %d", __FUNCTION__, __LINE__);
#define DO_STACKTEST         uint8_t __stacktest; if (basestack_ptr) do_stacktest(basestack_ptr-&__stacktest, __FUNCTION__);
void do_stacktest(int stack_usage, const char *fn);
#else
#define INIT_STACKTEST       ;
#define END_STACKTEST        ;
#define DO_STACKTEST         ;
#endif

uint8_t terminate_timer;    // used to in simulation shutdown
uint8_t global_status;      // used to display 0-15 global status with LEDs

void init_mutils();

char debug_str[256];
void format_debugstr();
void dbgout(char *fmt, ...);

void reverse_pathvec(ADDRESS *path, uint8_t len);
int find_pathpos(uint8_t path_len, ADDRESS *path, ADDRESS node);
void share_pathprefix(uint8_t path_len1, ADDRESS *path1, uint8_t *path_len2, ADDRESS **path2);

ADDRESS *alloc_addr(ADDRESS addr);
uint16_t compute_crc(ADDRESS addr, uint8_t *data, uint8_t len);

char *strupr(char *str);
void pause_sim();

void print_hexlist(char *s, uint8_t *l, int size);
void print_grouplist(uint8_t *group, int size);
void print_list(uint8_t *n, int count, char *l);
void print_path(ADDRESS *n, int count, char *l);
void print_tuple(ATTRIBUTE *n, int count, char *l);
void print_sel(uint8_t *sel);

#if defined (TOSSIM) || defined (UNIT_TEST)
void print_stack(void *s);
#endif
#ifdef TOSSIM
FILE *file_open(char *name, char *mask);
int check_routeterminate(uint8_t busy_flag, uint16_t node_count);
#endif

int encode_bitdiff(uint8_t *buffer1, uint8_t *buffer2, uint8_t len, uint8_t *diff, uint8_t max_diff);
int decode_bitdiff(uint8_t *buffer1, uint8_t *buffer2, uint8_t len, uint8_t *diff, uint8_t diff_len);

int32_t int_sqrt(int32_t n);

void compressASCII(uint8_t *buf, int16_t buf_len, uint8_t *out, int16_t *out_len);
void decompressASCII(uint8_t *buf, int16_t buf_len, uint8_t *out, int16_t *out_len);

uint32_t timercycles_to_seconds(uint32_t cycles);
uint32_t seconds_to_timercycles(uint32_t seconds);

uint8_t check_congestion();
uint8_t node_idle();

void set_globalstatus(uint8_t gs);
